﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Castle.ActiveRecord;
using NHibernate.Criterion;
using System.Web;
using Light.Framework.Model;

namespace Light.Framework.Castle
{
    /// <summary>
    /// 实体类持久化操作类
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class EntityMediator<T> where T : class, new()
    {

        public static void Create(T obj)
        {
            ActiveRecordMediator<T>.CreateAndFlush(obj);
        }

        public static void Update(T obj)
        {
            ActiveRecordMediator.UpdateAndFlush(obj);
        }

        public static void Save(T obj)
        {
            ActiveRecordMediator.Save(obj);
        }


        /// <summary>
        /// 标记为已删除
        /// </summary>
        /// <param name="obj"></param>
        public static void Delete(T obj)
        {
            ActiveRecordMediator.UpdateAndFlush(obj);

            //不进行物理删除
            //ActiveRecordMediator.DeleteAndFlush(obj);
        }


        public static void DeleteAll()
        {
            ActiveRecordMediator<T>.DeleteAll();
        }

        public static void DeleteAll(string where)
        {
            ActiveRecordMediator<T>.DeleteAll(where);
        }

        public static T Find(object id)
        {
            return ActiveRecordMediator<T>.FindByPrimaryKey(id);
        }


        public static List<T> FindAll()
        {
            T[] models = ActiveRecordMediator<T>.FindAll();
            if (models != null)
            {
                return models.ToList();
            }
            return null;
        }

        public static T TryFind(object id)
        {
            return ActiveRecordMediator<T>.FindByPrimaryKey(id, false);
        }



        /// <summary>
        /// 根据属性，值(唯一)获取实体
        /// </summary>
        /// <param name="property"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static T FindByProperty(string property, object value)
        {
            ICriterion criteria = (value == null) ? Expression.IsNull(property) : Expression.Eq(property, value);
            return ActiveRecordMediator<T>.FindFirst(criteria);
        }


        /// <summary>
        /// 根据ID删除
        /// </summary>
        /// <param name="id"></param>
        public static void Delete(object id)
        {
            T obj = Find(id);
            Delete(obj);
        }

        /// <summary>
        /// 根据属性值(唯一)删除实体
        /// </summary>
        /// <param name="property"></param>
        /// <param name="value"></param>
        public static void DeleteByProperty(string property, object value)
        {
            ICriterion criteria = (value == null) ? Expression.IsNull(property) : Expression.Eq(property, value);
            T obj = FindByProperty(property, value);
            ActiveRecordMediator<T>.Delete(obj);
        }

        /// <summary>
        /// 根据属性值获取
        /// </summary>
        /// <param name="property"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static List<T> FindAllByProperty(string property, object value)
        {
            ICriterion criteria = (value == null) ? Expression.IsNull(property) : Expression.Eq(property, value);
            T[] models = ActiveRecordMediator<T>.FindAll(criteria);
            if (models != null)
            {
                return models.ToList();
            }
            return null;
        }

        /// <summary>
        /// 根据属性值获取
        /// </summary>
        /// <param name="orderByColumn">排序字段（升序）</param>
        /// <param name="property">属性名称</param>
        /// <param name="value">属性值</param>
        /// <returns></returns>
        public static List<T> FindAllByProperty(string orderByColumn, string property, object value)
        {
            ICriterion criteria = (value == null) ? Expression.IsNull(property) : Expression.Eq(property, value);
            T[] models = ActiveRecordMediator<T>.FindAll(new Order[] { Order.Asc(orderByColumn) }, criteria);
            if (models != null)
            {
                return models.ToList();
            }
            return null;
        }

        #region 基于ICriterion查询

        public static int Count(params ICriterion[] criterions)
        {
            if (criterions == null || criterions.Length == 0)
                return ActiveRecordMediator<T>.Count();
            else
                return ActiveRecordMediator<T>.Count(criterions);
        }

        public static T FindOne(params ICriterion[] criterias)
        {
            return ActiveRecordMediator<T>.FindOne(criterias);
        }

        public static T FindOneOrDefault(params ICriterion[] criterias)
        {
            try
            {
                return ActiveRecordMediator<T>.FindOne(criterias);
            }
            catch (Exception ex)
            {

                return null;
            }

        }

        public static T FindFirst(params ICriterion[] criterias)
        {
            return ActiveRecordMediator<T>.FindFirst(criterias);

        }

        public static T FindFirst(Order[] orders, params ICriterion[] criterias)
        {
            return ActiveRecordMediator<T>.FindFirst(orders, criterias);
        }

        public static T FindFirst(ModelOrder order, params ICriterion[] criterias)
        {
            return ActiveRecordMediator<T>.FindFirst(order.Orders, criterias);
        }

        public static List<T> FindAll(params ICriterion[] criterias)
        {
            T[] models = ActiveRecordMediator<T>.FindAll(criterias);
            if (models != null)
            {
                return models.ToList();
            }
            return null;
        }

        public static List<T> FindAll(Order[] orders, params ICriterion[] criterias)
        {
            T[] models = ActiveRecordMediator<T>.FindAll(orders, criterias);
            if (models != null)
            {
                return models.ToList();
            }
            return null;
        }



        /// <summary>
        /// 查询
        /// </summary>
        /// <param name="firstResult">开始索引</param>
        /// <param name="maxresults">读取的数量</param>
        /// <param name="criterias">查询条件</param>
        /// <returns></returns>
        public static List<T> SlicedFindAll(int firstResult, int maxresults, params ICriterion[] criterias)
        {
            T[] models = ActiveRecordMediator<T>.SlicedFindAll(firstResult, maxresults, criterias);

            if (models != null)
            {
                return models.ToList();
            }
            return null;
        }

        /// <summary>
        /// 查询
        /// </summary>
        /// <param name="firstResult">开始索引</param>
        /// <param name="maxresults">读取的数量</param>
        /// <param name="orders">排序</param>
        /// <param name="criterias">查询条件</param>
        /// <returns></returns>
        public static List<T> SlicedFindAll(int firstResult, int maxresults, Order[] orders, params ICriterion[] criterias)
        {
            T[] models = ActiveRecordMediator<T>.SlicedFindAll(firstResult, maxresults, orders, criterias);

            if (models != null)
            {
                return models.ToList();
            }
            return null;
        }

        /// <summary>
        /// 查询
        /// </summary>
        /// <param name="pageIndex">当前页码（从1开始）</param>
        /// <param name="totalPage">总页数</param>
        /// <param name="totalResult">总记录条数</param>
        /// <param name="pageSize">每页记录数</param>
        /// <param name="criterias">查询条件</param>
        /// <returns></returns>
        public static List<T> SlicedFindAll(ref int pageIndex, out int totalPage, out int totalResult, int pageSize, params ICriterion[] criterias)
        {
            totalPage = 0;
            totalResult = 0;

            return SlicedFindAll(ref pageIndex, out totalPage, out totalResult, pageSize, null, criterias);
        }

        /// <summary>
        /// 查询
        /// </summary>
        /// <param name="pageIndex">当前页码（从1开始）</param>
        /// <param name="totalPage">总页数</param>
        /// <param name="totalResult">总记录条数</param>
        /// <param name="pageSize">每页记录数</param>
        /// <param name="orders">排序字段</param>
        /// <param name="criterias">查询条件</param>
        /// <returns></returns>
        public static List<T> SlicedFindAll(ref int pageIndex, out int totalPage, out int totalResult, int pageSize, Order[] orders, params ICriterion[] criterias)
        {

            totalResult = Count(criterias);
            totalPage = totalResult % pageSize == 0 ? totalResult / pageSize : (totalResult / pageSize + 1);

            if (pageIndex <= 0)
                pageIndex = 1;

            return SlicedFindAll((pageIndex - 1) * pageSize, pageSize, orders, criterias);

        }


        #endregion


        #region 基于DetachedCriteria查询

        public static int Count(DetachedCriteria criterions)
        {
            if (criterions == null)
                return ActiveRecordMediator<T>.Count();
            else
            {
                criterions.SetProjection(Projections.RowCount());
                return ActiveRecordMediator<T>.Count(criterions);
            }
        }

        public static T FindOne(DetachedCriteria criterias)
        {
            return ActiveRecordMediator<T>.FindOne(criterias);
        }

        public static T FindOneOrDefault(DetachedCriteria criterias)
        {
            try
            {
                return ActiveRecordMediator<T>.FindOne(criterias);
            }
            catch (Exception ex)
            {

                return default(T);
            }

        }

        public static T FindFirst(DetachedCriteria criterias)
        {
            return ActiveRecordMediator<T>.FindFirst(criterias);

        }

        public static T FindFirst(DetachedCriteria criterias, ModelOrder order)
        {
            return ActiveRecordMediator<T>.FindFirst(criterias, order.Orders);
        }

        public static T FindFirst(DetachedCriteria criterias, Order[] orders)
        {
            return ActiveRecordMediator<T>.FindFirst(criterias, orders);
        }

        public static List<T> FindAll(DetachedCriteria criterias)
        {
            T[] models = ActiveRecordMediator<T>.FindAll(criterias);
            if (models != null)
            {
                return models.ToList();
            }
            return null;
        }

        public static List<T> FindAll(Order[] orders, DetachedCriteria criterias)
        {
            T[] models = ActiveRecordMediator<T>.FindAll(criterias, orders);
            if (models != null)
            {
                return models.ToList();
            }
            return null;
        }



        /// <summary>
        /// 查询
        /// </summary>
        /// <param name="firstResult">开始索引</param>
        /// <param name="maxresults">读取的数量</param>
        /// <param name="criterias">查询条件</param>
        /// <returns></returns>
        public static List<T> SlicedFindAll(int firstResult, int maxresults, DetachedCriteria criterias)
        {
            T[] models = ActiveRecordMediator<T>.SlicedFindAll(firstResult, maxresults, criterias);

            if (models != null)
            {
                return models.ToList();
            }
            return null;
        }

        /// <summary>
        /// 查询
        /// </summary>
        /// <param name="firstResult">开始索引</param>
        /// <param name="maxresults">读取的数量</param>
        /// <param name="orders">排序</param>
        /// <param name="criterias">查询条件</param>
        /// <returns></returns>
        public static List<T> SlicedFindAll(int firstResult, int maxresults, Order[] orders, DetachedCriteria criterias)
        {
            criterias.SetProjection(null);
            criterias.SetResultTransformer(CriteriaSpecification.RootEntity);//解决搜索时，使用两次DetachedCriteria（一次获取总记录数，一次获取当前页数据）时出错的问题

            T[] models = ActiveRecordMediator<T>.SlicedFindAll(firstResult, maxresults, criterias, orders);

            if (models != null)
            {
                return models.ToList();
            }
            return null;
        }

        /// <summary>
        /// 查询
        /// </summary>
        /// <param name="pageIndex">当前页码（从1开始）</param>
        /// <param name="totalPage">总页数</param>
        /// <param name="totalResult">总记录条数</param>
        /// <param name="pageSize">每页记录数</param>
        /// <param name="criterias">查询条件</param>
        /// <returns></returns>
        public static List<T> SlicedFindAll(ref int pageIndex, out int totalPage, out int totalResult, int pageSize, DetachedCriteria criterias)
        {
            totalPage = 0;
            totalResult = 0;

            return SlicedFindAll(ref pageIndex, out totalPage, out totalResult, pageSize, null, criterias);
        }

        /// <summary>
        /// 查询
        /// </summary>
        /// <param name="pageIndex">当前页码（从1开始）</param>
        /// <param name="totalPage">总页数</param>
        /// <param name="totalResult">总记录条数</param>
        /// <param name="pageSize">每页记录数</param>
        /// <param name="orders">排序字段</param>
        /// <param name="criterias">查询条件</param>
        /// <returns></returns>
        public static List<T> SlicedFindAll(ref int pageIndex, out int totalPage, out int totalResult, int pageSize, Order[] orders, DetachedCriteria criterias)
        {
            //criterions.SetProjection(Projections.RowCount());
            totalResult = Count(criterias);

            totalPage = totalResult % pageSize == 0 ? totalResult / pageSize : (totalResult / pageSize + 1);

            if (pageIndex <= 0)
                pageIndex = 1;

            //criterias.SetProjection(null);
            //criterias.SetResultTransformer(CriteriaSpecification.RootEntity);

            return SlicedFindAll((pageIndex - 1) * pageSize, pageSize, orders, criterias);

        }


        #endregion

        public static object ExecuteQuery(IActiveRecordQuery q)
        {
            return ActiveRecordMediator<T>.ExecuteQuery(q);
        }

        public static SessionScope CurrentSessionScope
        {
            get
            {
                if (HttpContext.Current != null)
                {
                    return (HttpContext.Current.Items["nh.sessionscope"] as SessionScope);
                }
                return null;
            }
        }

        public static void SessionEvict(params T[] models)
        {
            if (models != null)
            {
                SessionScope currentSessionScope = CurrentSessionScope;
                if (currentSessionScope != null)
                {
                    foreach (T local in models)
                    {
                        if (local != null)
                        {
                            currentSessionScope.Evict(local);
                        }
                    }
                }
            }
        }
    }
}
